﻿using System;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Web;
using Autofac;
using Autofac.Integration.Mvc;
using TaskManager.Domain.BusinessObjects;
using TaskManager.Domain.Repositories;
using TaskManager.Web.Controls;

namespace TaskManager.Web.Modules
{
    /// <summary>
    /// Encapsulates services provided by Presentation Layer
    /// </summary>
    public class PresentationLayer : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            builder.RegisterFilterProvider();

            // Register MVC specific abstractions (HttpRequestBase,HttpResponceBase etc)
            builder.RegisterModule(new AutofacWebTypesModule());

            builder.RegisterType<TabContainer>()
                .InstancePerLifetimeScope()
                .CacheInSession();

            builder.Register(ExtractUserFromHttpContext)
                .InstancePerLifetimeScope();
        }

        private static User ExtractUserFromHttpContext(IComponentContext c)
        {
            Contract.Ensures(Contract.Result<User>() != null);

            var userRepository = c.Resolve<IUserRepository>();
            var httpContext = c.Resolve<HttpContextBase>();

            if(httpContext.Request.CurrentExecutionFilePath.Contains("TestServer"))
            {
                return ResolveTestServerUser(c, userRepository);
            }

            var user = userRepository.FindByName(httpContext.User.Identity.Name);

            return user;
        }

        private static User ResolveTestServerUser(IComponentContext c, IUserRepository userRepository)
        {
            // TestServerController does not require an authentication and we need to return
            // fake user in order to satisfy dependency resolution procedure.

            const string userName = "TestServerUser";

            User user = userRepository.FindByName(userName);

            if (user != null)
                return user;

            var unitOfWork = c.Resolve<IUnitOfWork>();

            Tuple<User, string> res = userRepository.CreateUser(userName, "123456", string.Empty, unitOfWork.Save);

            return res.Item1;
        }
    }
}